package ink.tiptop.common;

import ink.tiptop.common.cache.ECaches;
import ink.tiptop.common.cache.ICache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

/**
 * @author ink.tiptop.zjf
 * @Title: Ticket
 * @Package ink.tiptop.caffeine
 * @Description:
 * @date 2020-06-24 20:53
 */
@Component(value = "caffeineClient")
@Slf4j
public class CaffeineClient<V> implements ICache {

    @Autowired
    private CacheManager cacheManager;

    @Override
    public V getVal(String key) {
        return this.getVal(key, ECaches.DEFAULT);
    }

    @Override
    public boolean setVal(String key, Object val) {
        return this.setVal(key, val, ECaches.DEFAULT);
    }

    @Override
    public boolean del(String k) {
        return this.del(k, ECaches.DEFAULT);
    }

    @Override
    public V getVal(String k, ECaches eCaches) {
        log.debug("获取key为{}的值,缓存类型为:{}", k, eCaches.name());
        try {
            Cache cache = cacheManager.getCache(eCaches.name());
            if (cache != null) {
                return cache.get(k) == null ? null : (V) cache.get(k).get();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    @Override
    public List<V> getList(String k) {
        return getList(k, ECaches.DAY);
    }

    @Override
    public List<V> getList(String k, ECaches eCaches) {
        log.debug("获取key为{}的值,缓存类型为:{}", k, eCaches.name());
        List<V> vs = new ArrayList<>();
        try {
            Cache cache = cacheManager.getCache(eCaches.name());
            if (cache == null) {
                return new ArrayList<>();
            }
            if (k.endsWith("*")) {
                String nKey = k.replaceAll("\\*", "");
                List<String> keys = getKeys(cache, nKey);
                for (String key : keys) {
                    log.debug("列表获取key为{}的值,缓存类型为:{}", key, eCaches.name());
                    vs.add(this.getVal(key,eCaches));
                }
            } else {
                log.debug("列表获取key为{}的值,缓存类型为:{}", k, eCaches.name());
                vs.add(this.getVal(k,eCaches));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return vs;
    }

    /**
     获取模糊匹配的keys
     * @param cache
     * @param nKey
     * @return
     */
    private List<String> getKeys(Cache cache, String nKey) {
        List<String> keys = null;
        if (cache instanceof CaffeineCache) {
            CaffeineCache cacheManager = (CaffeineCache) cache;
            ConcurrentMap<Object, Object> objectObjectConcurrentMap = cacheManager.getNativeCache().asMap();
            keys = objectObjectConcurrentMap.keySet().parallelStream().map(nm -> nm.toString()).filter(name -> name.startsWith(nKey)).collect(Collectors.toList());
        }
        return keys;
    }

    @Override
    public boolean setVal(String k, Object v, ECaches eCaches) {
        log.debug("设置key为{}的值,缓存类型为:{}", k, eCaches.name());
        try {
            Cache cache = cacheManager.getCache(eCaches.name());
            if (cache != null) {
                cache.put(k, v);
                return true;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }


    @Override
    public boolean del(String k, ECaches eCaches) {
        try {
            Cache cache = cacheManager.getCache(eCaches.name());
            if (cache == null) {
                return false;
            }
            // 如果是以*结尾的,那就删除全部 匹配的key
            if (k.endsWith("*")) {
                String nKey = k.replaceAll("\\*", "");
                List<String> keys = getKeys(cache, nKey);
                for (String key : keys) {
                    log.debug("删除key为{}的值,缓存类型为:{}", key, eCaches.name());
                    cache.evict(key);
                }
            } else {
                log.debug("删除key为{}的值,缓存类型为:{}", k, eCaches.name());
                cache.evict(k);
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }


}
